package method

import (
	"bytes"
	"fmt"
	"io"
	"mall_admin_api/biz/util"
	"os"
	"strings"
	"text/template"
)

func GenerateExtraMethod(tableName string, noBizIDTableName []string, dalFilePath string) error {
	var buf bytes.Buffer
	err := render(Header, &buf, nil)
	if err != nil {
		return err
	}

	err = render(ServiceHeader, &buf, map[string]interface{}{
		"TableName": tableName,
	})
	if err != nil {
		return err
	}

	list := []string{MGet, GetByConditions, GetList, GetTotal, GetByID,
		GetListWithTotal, Create, CreateWithTx, BatchCreate, BatchCreateWithTx,
		Update, UpdateWithTx, Delete, DeleteWithTx,
	}
	list = util.Unique(list)
	for _, method := range list {
		if util.InArray(tableName, noBizIDTableName) {
			method = strings.ReplaceAll(method, Biz, "")
			method = strings.ReplaceAll(method, WhereBiz, "")
		}

		if err = render(method, &buf, map[string]interface{}{
			"TableName": tableName,
		}); err != nil {
			return err
		}
	}

	fileName := fmt.Sprintf("%s%s%s.extra.gen.go", dalFilePath, string(os.PathSeparator), toSnakeCase(tableName))
	if err = os.WriteFile(fileName, buf.Bytes(), 0644); err != nil {
		return err
	}
	return nil
}

func render(tmpl string, wr io.Writer, data interface{}) error {
	t, err := template.New(tmpl).Parse(tmpl)
	if err != nil {
		return err
	}
	return t.Execute(wr, data)
}

// 将驼峰命名转换为下划线命名
func toSnakeCase(in string) string {
	runes := []rune(in)
	output := make([]rune, 0, len(runes)+len(runes)/2)
	for i, r := range runes {
		if i > 0 && 'A' <= r && r <= 'Z' {
			output = append(output, '_', r+('a'-'A'))
		} else {
			output = append(output, r)
		}
	}
	return strings.ToLower(string(output))
}

func GenInitDAO(tableNames []string, dalFilePath string) error {
	var a = "package dal \n type InitDAO struct {"
	a = fmt.Sprintf("%s\n Q                           *Query", a)
	for _, name := range tableNames {
		a = fmt.Sprintf("%s\n    %sDAO *%sDAO", a, name, name)
	}
	a = fmt.Sprintf("%s\n }", a)
	a = fmt.Sprintf("%s\n func NewInitDAO(bizID int64) *InitDAO {\n return &InitDAO{", a)
	a = fmt.Sprintf("%s\n Q: Q,", a)
	for _, name := range tableNames {
		a = fmt.Sprintf("%s\n    %sDAO: new%sDAO(bizID),", a, name, name)
	}
	a = fmt.Sprintf("%s\n }\n }", a)
	fileName := fmt.Sprintf("%s%sinit.gen.go", dalFilePath, string(os.PathSeparator))
	if err := os.WriteFile(fileName, []byte(a), 0644); err != nil {
		return err
	}
	return nil
}
